Restrict and register image sizes

Pitfall By design
The scaled image URL (/foto.jpg/1200x800x0/navn.jpg) is open by default: every unique size is a cache miss with heavy scaling and a new cache file on disk. A size policy locks scaling to a known set of sizes — and it is also what unlocks WebP/AVIF, which are refused on the URL path until the policy is set to auto or strict.
Applies to: Imagessite.json

What you'll see

You just changed sizePolicy, or you are adopting WebP/AVIF, and something breaks. The symptoms:

  • Images suddenly return 400 after switching to strict — a size the page requests is not in allowedSizes.
  • An image comes back at a “nearly right” size under auto — it was snapped to the closest allowed size.
  • A size generated in client-side JS never shows up in “Scan now” — the scan only reads server-side source.
  • .webp/.avif is served as JPEG for as long as the policy is open.
  • Scaled images return 429 under load — the anti-DoS rate guard on scaling.

What's actually happening

The size key is WxHxM — the same string as the URL segment. WxH (no third part) is mode 0. There are three policy modes:

ModeBehaviour
open (default)Any size, only the maxDimension cap applies. .webp/.avif on the URL path is downgraded to JPEG/PNG.
autoAccepts allowedSizesdiscoveredSizes. An unknown size snaps to the nearest allowed one; the list self-expands from traffic and scan.
strictSame as auto, but an unknown size returns HTTP 400. No self-expansion.

Two lists with different ownership: allowedSizes is yours (owner-maintained, never touched by scan or passive discovery), while discoveredSizes is the machine's (append-only, deduped, passive growth capped at 100).

Snapping under auto only matches within the same scaling mode. If no allowed size exists with the requested mode, the request is rejected instead of snapped — that is the “nearly right size” symptom when the mode does not line up.

Under open, a requested .webp/.avif on the URL path is downgraded to JPEG/PNG. This is a DoS defence (see Use AVIF and WebP image formats, #26952): open has no size whitelist, so the URL could otherwise request arbitrary sizes in the heavier formats. Server-authored docly.scaleImage and attachFile64 are not subject to the policy.

What to do

Roll the policy on in order — start permissive, capture the real sizes, then lock down.

  1. Open Folder Properties → the “Image sizes” tab (requires publish rights on the folder).
  2. Set sizePolicy to auto. This starts passive discovery and lets you scan.
  3. Run “Scan now” (a static dry-run — it writes nothing), review the diff, then Apply changes.
  4. Promote the sizes you want to keep from Discovered to Allowed.
  5. Add client-JS-generated and dynamically computed sizes to allowedSizes by hand — the scan never sees them.
  6. Switch to strict and verify that no images return 400.

The images block lives in #/site.json (in the folder's # system folder), shared per folder, keys read case-insensitively:

{
  "images": {
    "defaultFormat": "webp",
    "sizePolicy": "auto",
    "onDisallowed": "nearest",
    "maxDimension": 2000,
    "allowedSizes": ["1200x800x0", "600x400x0", "128x128x1"],
    "discoveredSizes": ["1024x1024x0", "300x300x0"]
  }
}
images.*ValuesMeaning
defaultFormatauto | jpeg | png | webp | avifDefault output format. The file extension in linkImage always overrides.
sizePolicyopen (default) | auto | strictSee the mode table above.
onDisallowednearest | rejectOverrides the default for an unknown size (auto→nearest, strict→reject).
maxDimensionpx, default 2000Hard cap on W and H in all modes, including open. 0/unset ⇒ 2000.
allowedSizes["WxHxM", …]Owner-maintained. Never touched by scan or passive discovery. No cap.
discoveredSizes["WxHxM", …]Machine-maintained. Append-only + dedupe. Passive growth capped at 100.

Watch out: strict with an empty allowedSizes rejects every scaled image with 400 (warning strict_no_sizes). Promote at least one real size before you switch.

The full M-mode table (-15), the snapping algorithm and every linkImage overload live in the reference pages — see linkImage, scaleImage and the site.json reference.